<template>
  <div :class="rwClassName" :style="rwStyle">
    <ruler-canvas
        :vertical="vertical"
        :scale="scale"
        :width="width"
        :height="height"
        :start="start"
        :selectStart="selectStart"
        :selectLength="selectLength"
        :canvasConfigs="canvasConfigs"
        @onAddLine="handleNewLine"
        :isShowReferLine="isShowReferLine"
        @onIndicatorShow="handleIndicatorShow"
        @onIndicatorMove="handleIndicatorMove"
        @onIndicatorHide="handleIndicatorHide"
    >
    </ruler-canvas>
    <div class="lines" v-show="isShowReferLine">
      <ruler-line
          v-for="(v,i) in lines"
          :key="v+i"
          :index="i"
          :value="v >> 0"
          :scale="scale"
          :start="start"
          :thick="thick"
          :palette="palette"
          :vertical="vertical"
          :isShowReferLine="isShowReferLine"
          @onRemove="handleLineRemove"
          @onMouseDown="handleLineDown"
          @onRelease="handleLineRelease">
      </ruler-line>
    </div>
    <div class="indicator" :style="indicatorStyle" v-show="showIndicator">
      <div class="value">{{ rulerValue }}</div>
    </div>
  </div>
</template>

<script>
import { computed, defineComponent, ref, } from "vue";
import RulerLine from "./ruler-line.vue";
import RulerCanvas from "./ruler-canvas.vue";

export default defineComponent({
  name: "rulerWrapper",
  components: { RulerCanvas, RulerLine },
  props: {
    vertical: Boolean,
    scale: Number,
    width: Number,
    thick: Number,
    height: Number,
    start: Number,
    lines: Array,
    selectStart: Number,
    selectLength: Number,
    canvasConfigs: Object,
    palette: Object,
    isShowReferLine: Boolean,
    onShowRightMenu: Function,
    handleShowReferLine: Function,
  },
  emits: ["onLineChange",],
  setup(props, ctx) {
    const rulerValue = ref(0);
    const isDraggingLine = ref(false);
    const showIndicator = ref(false);
    const rwClassName = computed(() => {
      const className = props.vertical ? "v-container" : "h-container";
      return className;
    });
    const rwStyle = computed(() => {
      const hContainer = {
        width: `calc(100% - ${props.thick}px)`,
        height: `${props.thick + 1}px`,
        left: `${props.thick + 1}px`,
        pointerEvents:"auto",
      };
      const vContainer = {
        width: `${props.thick + 1}px`,
        height: `calc(100% - ${props.thick}px)`,
        top: `${props.thick + 1}px`,
        pointerEvents:"auto",
      };
      return props.vertical ? vContainer : hContainer;
    });
    const lineStyle = computed(() => {
      return {
        borderTop: `1px solid ${props.palette.lineColor}`,
        cursor: props.isShowReferLine ? "ns-resize" : "none"
      };
    });
    const indicatorStyle = computed(() => {
      const indicatorOffset = (rulerValue.value - props.start) * props.scale;
      let positionKey = props.vertical ? "top" : "left";
      let borderKey = props.vertical ? "borderBottom" : "borderLeft";
      return {
        [positionKey]: indicatorOffset + "px",
        [borderKey]: `1px solid ${props.palette.borderColor}`
      };
    });
    const handleNewLine = (value) => {
      props.lines.push(value);
      ctx.emit("onLineChange", props.lines, props.vertical);
    };
    const handleIndicatorShow = (value) => {
      if (!isDraggingLine.value) {
        showIndicator.value = true;
        rulerValue.value = value;
      }
    };
    const handleLineRemove = (index) => {
      props.lines.splice(index, 1);
      ctx.emit("onLineChange", props.lines, props.vertical);
    };
    const handleLineRelease = (value, index) => {
      isDraggingLine.value = false;
      const offset = value - props.start;
      const maxOffset = (props.vertical ? props.height : props.width) / props.scale;

      if (offset < 0 || offset > maxOffset) {
        handleLineRemove(index);
      } else {
        props.lines[index] = value;
        ctx.emit("onLineChange", props.lines, props.vertical);
      }
    };
    const handleLineDown = () => {
      isDraggingLine.value = true;
    };
    const handleIndicatorMove = (value) => {
      if (showIndicator.value) {
        rulerValue.value = value;
      }
    };
    const handleIndicatorHide = (value) => {
      showIndicator.value = false;
    };
    return {
      rwClassName,
      rwStyle,
      lineStyle,
      showIndicator,
      rulerValue,
      handleLineRelease,
      handleIndicatorShow,
      handleNewLine,
      indicatorStyle,
      handleLineRemove,
      handleLineDown,
      handleIndicatorHide,
      handleIndicatorMove
    };
  }
});
</script>

<style lang="less" scoped>
.line {
  position: absolute;
}

.indicator {
  position: absolute;
  pointer-events: none;

  .value {
    position: absolute;
    background: transparent;
  }
}

.h-container, .v-container {
  position: absolute;

  .lines {
    pointer-events: none;
  }

  &:hover .lines {
    pointer-events: auto;
  }
}

.h-container {
  top: 0;

  .line {
    height: 100vh;
    top: 0;
    padding-left: 5px;

    .action {
      transform: translateX(-24px);

      .value {
        margin-left: 4px;
      }
    }
  }

  .indicator {
    top: 0;
    height: 100vw;

    .value {
      padding: 0 2px;
      width: auto;
      margin-left: 4px;
      margin-top: 4px;
    }
  }
}

.v-container {
  left: 0;

  .line {
    width: 100vw;
    left: 0;
    padding-top: 5px;

    .action {
      transform: translateY(-24px);
      flex-direction: column;

      .value {
        margin-top: 4px;
      }
    }
  }

  .indicator {
    width: 100vw;

    .value {
      padding: 0 2px;
      width: auto;
      left: 0px;
      margin-left: 2px;
      margin-top: -5px;
      transform-origin: 0 0;
      transform: rotate(-90deg);
    }
  }
}
</style>